﻿#pragma once
#include "zyEnvironment.h"

namespace BlackMoonUI {

    class resObject;

    typedef void(WINAPI* FnResDestroy)(resObject*);

    class resObject {
    private:
        LPVOID m_pSelf;
        std::atomic_size_t m_refCount;
        std::unique_ptr<LONG_PTR[]> m_pData;
        FnResDestroy m_fnDestroy;

        resObject() : m_pSelf(this),
                      m_refCount(1),
                      m_pData(std::make_unique<LONG_PTR[]>(16)),
                      m_fnDestroy(nullptr) {}

        ~resObject() {
            m_pSelf = nullptr;
            m_fnDestroy = nullptr;
        }

    public:
        static resObject* Create() { return new resObject(); }

    public:
        void setDestroy(FnResDestroy fnDestroy) { m_fnDestroy = fnDestroy; }
        void callDestroy() {
            if (m_fnDestroy)
                m_fnDestroy(this);
        }

        BOOL checkSelf() const { return m_pSelf == this; }

        size_t getRefCount() const noexcept { return m_refCount.load(); }

        size_t addRef() noexcept { return m_refCount.fetch_add(1) + 1; }

        size_t release() noexcept {
            size_t count = m_refCount.fetch_sub(1) - 1;
            if (count == 0) {
                if (m_fnDestroy)
                    m_fnDestroy(this);
                delete this;
            }
            return count;
        }

        BOOL setDataValue(LONG_PTR value, size_t index = 0) {
            if (index >= 16 || !m_pData) return FALSE;
            m_pData[index] = value;
            return TRUE;
        }

        LONG_PTR getDataValue(size_t index = 0) const {
            if (index < 16) return m_pData[index];
            return 0;
        }

        LONG_PTR* getDataPtr() { return m_pData.get(); }
    };

    class zyRes {
    protected:
        resObject* m_obj;

    public:
        zyRes() : m_obj(resObject::Create()) {
            m_obj->setDestroy(zyRes_Destroy);
        }
        ~zyRes() { m_obj->release(); }
        // 在zyRes类中添加拷贝构造和赋值运算符
        zyRes(const zyRes& other) : m_obj(other.m_obj) {
            m_obj->addRef();
        }

        zyRes& operator=(const zyRes& other) {
            if (this != &other) {
                m_obj->release();
                m_obj = other.m_obj;
                m_obj->addRef();
            }
            return *this;
        }

        // 添加移动语义支持
        zyRes(zyRes&& other) noexcept : m_obj(other.m_obj) {
            other.m_obj = nullptr;
        }

        zyRes& operator=(zyRes&& other) noexcept {
            if (this != &other) {
                m_obj->release();
                m_obj = other.m_obj;
                other.m_obj = nullptr;
            }
            return *this;
        }
        resObject* getObject(BOOL bAddRef = FALSE) const {
            if (bAddRef) m_obj->addRef();
            return m_obj;
        }

        resObject* 取对象(BOOL 添加引用 = FALSE) const { return getObject(添加引用); }

        BOOL setObject(resObject* newObj, BOOL bAddRef = TRUE) {
            if (newObj == NULL || !m_obj->checkSelf()) return FALSE;
            if (newObj == m_obj) return TRUE;
            m_obj->release();
            m_obj = newObj;
            if (bAddRef) m_obj->addRef();
            return TRUE;
        }

        BOOL 置对象(resObject* 新对象, BOOL 添加引用 = TRUE) { return setObject(新对象, 添加引用); }

        BOOL SetMember(LONG_PTR value, size_t index = 0) { return m_obj->setDataValue(value, index); }

        LONG_PTR GetMember(size_t index = 0) const { return m_obj->getDataValue(index); }

    protected:
        static void zyRes_Destroy(resObject* obj) { };
    };

    class zyIcon : public zyRes {
    public:
        zyIcon() { m_obj->setDestroy(zyIcon_Destroy); }
        ~zyIcon() {  }
        
        BOOL setIcon(HICON hIcon) {
            if (!m_obj->checkSelf()) return FALSE;
            m_obj->setDataValue((LONG_PTR)hIcon);
            return TRUE;
        }

        HICON getIcon() const {
            if (!m_obj->checkSelf()) return NULL;
            return (HICON)m_obj->getDataValue();
        }

        void 销毁() {
            HICON hIcon = (HICON)m_obj->getDataValue();
            if (hIcon != 0) {
                ICONINFO info = { 0 };
                GetIconInfo(hIcon, &info);
                if (info.fIcon == 0) {
                    DestroyCursor(hIcon);
                }
                else {
                    DestroyIcon(hIcon);
                }
                if (info.hbmColor != 0) {
                    DeleteObject(info.hbmColor);
                }
                if (info.hbmMask != 0) {
                    DeleteObject(info.hbmMask);
                }
                m_obj->setDataValue((LONG_PTR)0);
            }
        }
        bool 载入文件(const std::wstring& rcName, bool 参数_是否光标 = false,int 参数_宽度 = 48,int 参数_高度 = 48) {
            销毁();
            HICON hIcon = (HICON)LoadImage(zyEnv::getInstance().getHandle(),rcName.c_str(),参数_是否光标 ? IMAGE_CURSOR :IMAGE_ICON, 参数_宽度, 参数_高度, LR_LOADFROMFILE);
            m_obj->setDataValue((LONG_PTR)hIcon);
            return hIcon != 0;
        }
        bool 载入图标(int 参数_资源ID) {
            销毁();
            HICON hIcon = LoadIcon(zyEnv::getInstance().getHandle(), MAKEINTRESOURCE(参数_资源ID));
            m_obj->setDataValue((LONG_PTR)hIcon);
            return hIcon != 0;
        }
        bool 载入系统图标(int 参数_类型) {
            销毁();
            HICON hIcon = LoadIcon(0, MAKEINTRESOURCE(参数_类型));
            m_obj->setDataValue((LONG_PTR)hIcon);
            return hIcon != 0;
        }
        bool 载入光标(int 参数_资源ID) {
            销毁();
            HCURSOR hIcon = LoadCursor(zyEnv::getInstance().getHandle(), MAKEINTRESOURCE(参数_资源ID));
            m_obj->setDataValue((LONG_PTR)hIcon);
            return hIcon != 0;
        }
        bool 载入系统光标(LPCWSTR 参数_类型) {
            销毁();
            HCURSOR hIcon = LoadCursor(0, 参数_类型);
            m_obj->setDataValue((LONG_PTR)hIcon);
            return hIcon != 0;
        }
        HICON 克隆句柄() { return CopyIcon((HICON)m_obj->getDataValue()); }
    protected:
        static void zyIcon_Destroy(resObject* obj) {
            HICON hIcon = (HICON)obj->getDataValue();
            if (hIcon != 0) {
                ICONINFO info = { 0 };
                GetIconInfo(hIcon, &info);
                if (info.fIcon == 0) {
                    DestroyCursor(hIcon);
                }
                else {
                    DestroyIcon(hIcon);
                }
                if (info.hbmColor != 0) {
                    DeleteObject(info.hbmColor);
                }
                if (info.hbmMask != 0) {
                    DeleteObject(info.hbmMask);
                }
                obj->setDataValue((LONG_PTR)0);
            }
            zyRes::zyRes_Destroy(obj);
        }

    };


}